/**
 * 加密工具
 * 提供数据加密和解密功能
 */

// 使用固定密钥（在实际应用中，应该使用设备指纹或用户密码）
const ENCRYPTION_KEY = 'ACCOUNTBOX_ENCRYPTION_KEY_2024';

/**
 * 跨平台的 TextEncoder 实现
 * @param {string} str 字符串
 * @returns {Uint8Array} 字节数组
 */
function textEncode(str) {
	// 如果支持原生 TextEncoder，优先使用
	if (typeof TextEncoder !== 'undefined') {
		return new TextEncoder().encode(str);
	}
	
	// 否则手动实现 UTF-8 编码
	const utf8 = [];
	for (let i = 0; i < str.length; i++) {
		let charCode = str.charCodeAt(i);
		if (charCode < 0x80) {
			utf8.push(charCode);
		} else if (charCode < 0x800) {
			utf8.push(0xc0 | (charCode >> 6));
			utf8.push(0x80 | (charCode & 0x3f));
		} else if ((charCode & 0xfc00) === 0xd800 && (str.charCodeAt(i + 1) & 0xfc00) === 0xdc00) {
			// 处理代理对（surrogate pairs）
			charCode = 0x10000 + (((charCode & 0x03ff) << 10) | (str.charCodeAt(++i) & 0x03ff));
			utf8.push(0xf0 | (charCode >> 18));
			utf8.push(0x80 | ((charCode >> 12) & 0x3f));
			utf8.push(0x80 | ((charCode >> 6) & 0x3f));
			utf8.push(0x80 | (charCode & 0x3f));
		} else {
			utf8.push(0xe0 | (charCode >> 12));
			utf8.push(0x80 | ((charCode >> 6) & 0x3f));
			utf8.push(0x80 | (charCode & 0x3f));
		}
	}
	return new Uint8Array(utf8);
}

/**
 * 跨平台的 TextDecoder 实现
 * @param {Uint8Array} bytes 字节数组
 * @returns {string} 字符串
 */
function textDecode(bytes) {
	// 如果支持原生 TextDecoder，优先使用
	if (typeof TextDecoder !== 'undefined') {
		const decoder = new TextDecoder('utf-8', { fatal: false });
		return decoder.decode(bytes);
	}
	
	// 否则手动实现 UTF-8 解码
	let result = '';
	let i = 0;
	
	while (i < bytes.length) {
		let byte1 = bytes[i++];
		
		if (byte1 < 0x80) {
			result += String.fromCharCode(byte1);
		} else if ((byte1 >> 5) === 0x06) {
			// 2字节字符
			let byte2 = bytes[i++];
			result += String.fromCharCode(((byte1 & 0x1f) << 6) | (byte2 & 0x3f));
		} else if ((byte1 >> 4) === 0x0e) {
			// 3字节字符
			let byte2 = bytes[i++];
			let byte3 = bytes[i++];
			result += String.fromCharCode(((byte1 & 0x0f) << 12) | ((byte2 & 0x3f) << 6) | (byte3 & 0x3f));
		} else if ((byte1 >> 3) === 0x1e) {
			// 4字节字符（代理对）
			let byte2 = bytes[i++];
			let byte3 = bytes[i++];
			let byte4 = bytes[i++];
			const codePoint = ((byte1 & 0x07) << 18) | ((byte2 & 0x3f) << 12) | ((byte3 & 0x3f) << 6) | (byte4 & 0x3f);
			if (codePoint > 0xffff) {
				const surrogate1 = 0xd800 + ((codePoint - 0x10000) >> 10);
				const surrogate2 = 0xdc00 + ((codePoint - 0x10000) & 0x3ff);
				result += String.fromCharCode(surrogate1, surrogate2);
			} else {
				result += String.fromCharCode(codePoint);
			}
		}
	}
	
	return result;
}

/**
 * 生成加密密钥哈希
 * @param {string} key 密钥
 * @returns {number} 密钥哈希值
 */
function generateKeyHash(key) {
	let hash = 0;
	for (let i = 0; i < key.length; i++) {
		const char = key.charCodeAt(i);
		hash = ((hash << 5) - hash) + char;
		hash = hash & hash; // 转换为32位整数
	}
	return hash;
}

/**
 * Base64 编码
 * @param {Uint8Array} bytes 字节数组
 * @returns {string} Base64 字符串
 */
function base64Encode(bytes) {
	const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
	let base64 = '';
	let i = 0;
	while (i < bytes.length) {
		const a = bytes[i++];
		const b = i < bytes.length ? bytes[i++] : 0;
		const c = i < bytes.length ? bytes[i++] : 0;
		
		const bitmap = (a << 16) | (b << 8) | c;
		base64 += chars.charAt((bitmap >> 18) & 63);
		base64 += chars.charAt((bitmap >> 12) & 63);
		base64 += i - 2 < bytes.length ? chars.charAt((bitmap >> 6) & 63) : '=';
		base64 += i - 1 < bytes.length ? chars.charAt(bitmap & 63) : '=';
	}
	return base64;
}

/**
 * Base64 解码
 * @param {string} base64 Base64 字符串
 * @returns {Uint8Array} 字节数组
 */
function base64Decode(base64) {
	const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
	const bytes = [];
	let i = 0;
	
	base64 = base64.replace(/[^A-Za-z0-9+/]/g, ''); // 移除填充字符
	
	while (i < base64.length) {
		const encoded1 = chars.indexOf(base64.charAt(i++));
		const encoded2 = chars.indexOf(base64.charAt(i++));
		const encoded3 = chars.indexOf(base64.charAt(i++));
		const encoded4 = chars.indexOf(base64.charAt(i++));
		
		const bitmap = (encoded1 << 18) | (encoded2 << 12) | (encoded3 << 6) | encoded4;
		
		bytes.push((bitmap >> 16) & 255);
		if (encoded3 !== 64) bytes.push((bitmap >> 8) & 255);
		if (encoded4 !== 64) bytes.push(bitmap & 255);
	}
	
	return new Uint8Array(bytes);
}

/**
 * 加密数据
 * @param {string} data 原始数据（JSON 字符串）
 * @param {string} key 加密密钥（可选，默认使用固定密钥）
 * @returns {string} 加密后的 Base64 字符串
 */
export function encryptData(data, key = ENCRYPTION_KEY) {
	try {
		// 生成密钥哈希
		const passwordHash = generateKeyHash(key);
		
		// 将字符串转换为字节数组（跨平台实现）
		const dataBytes = textEncode(data);
		
		// XOR 加密
		const encryptedBytes = [];
		for (let i = 0; i < dataBytes.length; i++) {
			const keyByte = (passwordHash + i) % 256;
			encryptedBytes.push(dataBytes[i] ^ keyByte);
		}
		
		// Base64 编码
		const base64 = base64Encode(new Uint8Array(encryptedBytes));
		
		// 添加标识前缀，方便识别加密数据
		return 'ENC:' + base64;
	} catch (error) {
		throw new Error('加密失败: ' + error.message);
	}
}

/**
 * 解密数据
 * @param {string} encryptedData 加密后的 Base64 字符串
 * @param {string} key 解密密钥（可选，默认使用固定密钥）
 * @returns {string} 解密后的原始数据（JSON 字符串）
 */
export function decryptData(encryptedData, key = ENCRYPTION_KEY) {
	try {
		// 检查输入类型
		if (typeof encryptedData !== 'string') {
			throw new Error('解密数据必须是字符串类型');
		}
		
		// 检查是否为加密数据
		if (!encryptedData.startsWith('ENC:')) {
			// 如果不是加密数据，直接返回（兼容旧数据）
			return encryptedData;
		}
		
		// 移除标识前缀
		const base64 = encryptedData.substring(4);
		
		// 验证 Base64 字符串
		if (!base64 || base64.length === 0) {
			throw new Error('Base64 数据为空');
		}
		
		// Base64 解码
		let encryptedBytes;
		try {
			encryptedBytes = base64Decode(base64);
		} catch (e) {
			throw new Error('Base64 解码失败: ' + e.message);
		}
		
		if (!encryptedBytes || encryptedBytes.length === 0) {
			throw new Error('解密后的字节数组为空');
		}
		
		// 生成密钥哈希
		const passwordHash = generateKeyHash(key);
		
		// XOR 解密
		const decryptedBytes = [];
		for (let i = 0; i < encryptedBytes.length; i++) {
			const keyByte = (passwordHash + i) % 256;
			decryptedBytes.push(encryptedBytes[i] ^ keyByte);
		}
		
		// 转换为字符串（跨平台实现）
		const result = textDecode(new Uint8Array(decryptedBytes));
		
		// 验证结果
		if (!result || result.length === 0) {
			throw new Error('解密后的字符串为空');
		}
		
		return result;
	} catch (error) {
		// 返回更详细的错误信息，但不要抛出异常，让上层处理
		console.error('解密过程详细错误:', error);
		throw error;
	}
}

/**
 * 检查数据是否为加密数据
 * @param {any} data 数据
 * @returns {boolean} 是否为加密数据
 */
export function isEncrypted(data) {
	return typeof data === 'string' && data.startsWith('ENC:');
}

